using System;
using System.Collections.Generic;
using System.Text;
using PDLib;

namespace PDLibTest
{
    class Tank { }
    class Soldier { }

    class SoldierTypeA : Soldier
    {
    }
    class SoldierTypeB : Soldier
    {
    }

    class TankA : Tank
    {
    }

    class TankB : Tank
    {
    }

    class Army
    {
        public List<Tank> tanks;
        public List<Soldier> soldiers;

        public Army()
        {
            tanks = new List<Tank>();
            soldiers = new List<Soldier>();
        }
        public static Army Generate(int size)
        {
            Army ret = new Army();
            Distribution<bool> b = Distributions.Bernoulli(0.2);
            Distribution<Tank> tg = new Distribution<Tank>(TankGenerator());
            Distribution<Soldier> sg = new Distribution<Soldier>(SoldierGenerator());
            for (int i = 0; i < size; i++)
            {
                if (b.NextSample())
                    ret.tanks.Add(tg.NextSample());
                else
                    ret.soldiers.Add(sg.NextSample());
            }
            return ret;
        }
        static IEnumerator<Tank> TankGenerator()
        {
            foreach (bool b in  Distributions.Bernoulli(0.4))
                yield return b ? ((Tank)new TankA()) : ((Tank)new TankB());
        }
        static IEnumerator<Soldier> SoldierGenerator()
        {
            foreach (bool b in Distributions.Bernoulli(0.6))
                yield return b ? ((Soldier)new SoldierTypeA()) : ((Soldier)new SoldierTypeB());
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            // Use directly of Sampling Functions
            // We don't need Distribution extra facilities;
            Distribution<bool> b = Distributions.Bernoulli(0.3);
            int count = 0;
            for (int i = 0; i < 100000; i++)
                if (b.NextSample()) count++;
            Console.WriteLine(count);

            Army a = Army.Generate(1000);
            int sa = 0, sb = 0, ta = 0, tb = 0;
            foreach (Soldier s in a.soldiers)
                if (s is SoldierTypeA) sa++;
                else sb++;
            foreach (Tank t in a.tanks)
                if (t is TankA) ta++;
                else tb++;
            Console.WriteLine("Soldiers A({0}) B({1}), Tanks A({2}) B({3})", sa, sb, ta, tb);
        }
    }
}
